package com.ltx.bugseeker.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.ltx.bugseeker.entity.User;
import com.ltx.bugseeker.dto.SmsLoginDTO;
import com.ltx.bugseeker.dto.SetPasswordDTO;
import com.ltx.bugseeker.entry.dto.LoginDTO;
import com.ltx.bugseeker.entry.vo.LoginVO;
import com.ltx.bugseeker.entry.vo.UserVO;
import com.ltx.bugseeker.vo.SmsLoginVO;
import com.ltx.bugseeker.exception.BusinessException;
import jakarta.servlet.http.HttpServletRequest;

/**
 * 用户服务接口
 * 继承MyBatis Plus的IService，提供用户相关的业务操作
 *
 * @author ltx
 * @since 2025-10-20 14:43:42
 */
public interface IUserService extends IService<User> {

    /**
     * 用户登录
     * 验证用户凭据并生成访问令牌
     *
     * @param loginDTO 登录请求参数
     * @param request  HTTP请求对象，用于获取客户端信息
     * @return 登录响应信息，包含用户信息和令牌
     * @throws com.ltx.bugseeker.exception.BusinessException 当登录失败时抛出业务异常
     */
    LoginVO login(LoginDTO loginDTO, HttpServletRequest request);

    /**
     * 用户登出
     * 清除用户的登录状态和令牌
     *
     * @return true表示登出成功，false表示登出失败
     */
    boolean logout();

    /**
     * 根据用户名查询用户
     * 支持用户名和邮箱两种方式查询
     *
     * @param username 用户名或邮箱
     * @return 用户实体对象，如果不存在则返回null
     */
    User getUserByUsername(String username);

    /**
     * 根据用户ID获取用户信息
     * 返回用户的详细信息，不包含敏感数据
     *
     * @param userId 用户ID
     * @return 用户视图对象
     * @throws com.ltx.bugseeker.exception.BusinessException 当用户不存在时抛出业务异常
     */
    UserVO getUserInfo(Long userId);

    /**
     * 验证密码
     * 校验明文密码与加密密码是否匹配
     *
     * @param rawPassword     明文密码
     * @param encodedPassword 加密密码
     * @return true表示密码正确，false表示密码错误
     */
    boolean verifyPassword(String rawPassword, String encodedPassword);

    /**
     * 更新用户最后登录信息
     * 记录用户的最后登录时间和IP地址
     *
     * @param userId  用户ID
     * @param loginIp 登录IP地址
     * @return true表示更新成功，false表示更新失败
     */
    boolean updateLastLoginInfo(Long userId, String loginIp);

    /**
     * 增加登录失败次数
     * 用于账户安全策略，记录登录失败次数
     *
     * @param userId 用户ID
     * @return true表示更新成功，false表示更新失败
     */
    boolean increaseLoginFailCount(Long userId);

    /**
     * 重置登录失败次数
     * 登录成功后重置失败计数
     *
     * @param userId 用户ID
     * @return true表示重置成功，false表示重置失败
     */
    boolean resetLoginFailCount(Long userId);

    /**
     * 锁定用户账户
     * 当登录失败次数过多时锁定账户
     *
     * @param userId      用户ID
     * @param lockMinutes 锁定时长（分钟）
     * @return true表示锁定成功，false表示锁定失败
     */
    boolean lockUser(Long userId, int lockMinutes);

    /**
     * 检查用户账户状态
     * 验证用户是否可以正常登录
     *
     * @param user 用户实体对象
     * @throws com.ltx.bugseeker.exception.BusinessException 当账户状态异常时抛出业务异常
     */
    void checkUserStatus(User user);

    /**
     * 获取当前登录用户信息
     *
     * @param userId 用户ID
     * @return 登录用户信息VO对象
     * @throws BusinessException 当用户不存在时抛出业务异常
     */
    LoginVO getCurrentUserInfo(Long userId);

    /**
     * 刷新访问令牌
     *
     * @param refreshToken 刷新令牌
     * @return 新的登录信息VO对象
     * @throws BusinessException 当刷新令牌无效时抛出业务异常
     */
    LoginVO refreshToken(String refreshToken);

    /**
     * 检查用户名是否可用
     *
     * @param username 用户名
     * @return true表示可用，false表示已被使用
     * @throws com.ltx.bugseeker.exception.BusinessException 当参数无效时抛出业务异常
     */
    boolean checkUsernameAvailability(String username);
    
    /**
     * 短信验证码登录
     * 使用手机号和短信验证码进行登录
     *
     * @param smsLoginDTO 短信登录请求参数
     * @param request HTTP请求对象，用于获取客户端信息
     * @return 短信登录响应信息，包含用户信息和令牌
     * @throws BusinessException 当登录失败时抛出业务异常
     */
    SmsLoginVO smsLogin(SmsLoginDTO smsLoginDTO, HttpServletRequest request);
    
    /**
     * 根据手机号查询用户
     * 
     * @param phone 手机号码
     * @return 用户实体对象，如果不存在则返回null
     */
    User getUserByPhone(String phone);
    
    /**
     * 创建新用户（通过手机号）
     * 
     * @param phone 手机号码
     * @param clientIp 客户端IP地址
     * @return 新创建的用户实体对象
     * @throws BusinessException 当创建失败时抛出业务异常
     */
    User createUserByPhone(String phone, String clientIp);
    
    /**
     * 设置用户密码
     * 用于首次登录后设置密码
     *
     * @param userId 用户ID
     * @param setPasswordDTO 设置密码请求参数
     * @return true表示设置成功，false表示设置失败
     * @throws BusinessException 当设置失败时抛出业务异常
     */
    boolean setPassword(Long userId, SetPasswordDTO setPasswordDTO);
    
    /**
     * 检查手机号是否已存在
     *
     * @param phone 手机号码
     * @return true表示已存在，false表示不存在
     */
    boolean checkPhoneExists(String phone);
}